﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Collections.ObjectModel;
using System.Reflection;
using System.IO;
using System.Web.Compilation;
using MicroDal.Context;

namespace MicroDal.Providers
{
    internal abstract class DbResourceFactory
    {
        internal static Cache<string, Type> s_typeCache = new Cache<string, Type>(name =>
        {
            var names = name.Split('.');
            var type = Type.GetType(string.Format("MicroDal.Providers.{0}Resource", names.Last()), false);
            if (type == null)
                type = Type.GetType(string.Format("MicroDal.Providers.{0}Resource, MicroDal.{0}Provider", names.Last()), false);
            return type;
        });

        public static IDbResource Create(string name)
        {
            if (name == null)
                throw new ArgumentNullException();

            if (ConfigurationManager.ConnectionStrings == null)
                throw new ConfigurationErrorsException("No connectionstrings in configuration");

            if (ConfigurationManager.ConnectionStrings[name] == null)
                throw new ArgumentException("Unknown connectionname: " + name + " in configuration");

            ConnectionStringSettings connectionSetting = ConfigurationManager.ConnectionStrings[name];

            if (string.IsNullOrEmpty(connectionSetting.ProviderName))
                throw new ConfigurationErrorsException("The connectionstring should have a ProviderName property in configuration. Ex. System.Data.SqlClient");

            return InitializeResource(connectionSetting);
        }

        public static IDbResource Create(string connectionstring, string providerName)
        {
            if (string.IsNullOrEmpty(connectionstring))
                throw new ArgumentException("The connectionstring can't be null or empty");
            if (string.IsNullOrEmpty(providerName))
                throw new ArgumentException("ProviderName can't be null or empty. Ex. 'System.Data.SqlClient'");

            ConnectionStringSettings connectionSetting = new ConnectionStringSettings("MDCon", connectionstring, providerName);
            return InitializeResource(connectionSetting);
        }

        private static IDbResource InitializeResource(ConnectionStringSettings connectionSetting)
        {
            var type = s_typeCache.Get(connectionSetting.ProviderName);

            if (type != null)
                return (IDbResource)Activator.CreateInstance(type, connectionSetting.ConnectionString);

            throw new NotSupportedException("No provider for client: " + connectionSetting.ProviderName);
        }
    }
}
